package utils

import "reflect"

func InArray(source interface{}, container interface{}) bool {
	st := reflect.ValueOf(source)
	switch st.Kind() {
	case reflect.Array, reflect.Slice:
		ct := reflect.ValueOf(container)
		if st.Len() > 0 && st.Index(0).Type() == ct.Type() {
			for i := 0; i < st.Len(); i++ {
				if st.Index(i).Interface() == ct.Interface() {
					return true
				}
			}
		}
		return false
	default:
		return false
	}
}

func Filter(arr interface{}, condition func(interface{}) bool) []interface{} {
	av := reflect.ValueOf(arr)
	switch av.Kind() {
	case reflect.Array, reflect.Slice:
		var res []interface{}
		for i := 0; i < av.Len(); i++ {
			avi := av.Index(i).Interface()
			if condition(avi) {
				res = append(res, avi)
			}
		}
		return res
	default:
		panic("")
	}
}

func Map(arr interface{}, condition func(interface{}) interface{}) []interface{} {
	av := reflect.ValueOf(arr)
	switch av.Kind() {
	case reflect.Array, reflect.Slice:
		var res []interface{}
		for i := 0; i < av.Len(); i++ {
			res = append(res, condition(av.Index(i).Interface()))
		}
		return res
	default:
		panic("")
	}
}

func Reduce(arr interface{}, condition func(interface{}, interface{}) interface{}) interface{} {
	av := reflect.ValueOf(arr)
	switch av.Kind() {
	case reflect.Array, reflect.Slice:
		avLen := av.Len()
		if avLen >= 2 {
			var res = av.Index(0).Interface()
			for i := 1; i < avLen; i++ {
				res = condition(res, av.Index(i).Interface())
			}
			return res
		} else if avLen == 1 {
			return av.Index(0)
		} else {
			return nil
		}
	default:
		panic("")
	}
}
